home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 1 / Cream of the Crop 1.iso / PROGRAM / GAS_1_38.ARJ / APP.C < prev    next >
C/C++ Source or Header  |  1990-10-11  |  8KB  |  393 lines

  1. /* This is the Assembler Pre-Processor
  2.    Copyright (C) 1987 Free Software Foundation, Inc.
  3.  
  4. This file is part of GAS, the GNU Assembler.
  5.  
  6. GAS is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 1, or (at your option)
  9. any later version.
  10.  
  11. GAS is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GAS; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. /* App, the assembler pre-processor.  This pre-processor strips out excess
  21.    spaces, turns single-quoted characters into a decimal constant, and turns
  22.    # <number> <filename> <garbage> into a .line <number>;.file <filename> pair.
  23.    This needs better error-handling.
  24.  */
  25. #include <stdio.h>
  26. #ifdef USG
  27. #define bzero(s,n) memset(s,0,n)
  28. #endif
  29. #if !defined(__STDC__) && !defined(const)
  30. #define const /* Nothing */
  31. #endif
  32.  
  33. static char    lex [256];
  34. static const char    symbol_chars[] = 
  35.     "$._ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
  36.  
  37. extern const char comment_chars[];
  38. extern const char line_comment_chars[];
  39.  
  40. #define LEX_IS_SYMBOL_COMPONENT        (1)
  41. #define LEX_IS_WHITESPACE        (2)
  42. #define LEX_IS_LINE_SEPERATOR        (4)
  43. #define LEX_IS_COMMENT_START        (8)    /* JF added these two */
  44. #define LEX_IS_LINE_COMMENT_START    (16)
  45. #define IS_SYMBOL_COMPONENT(c)        (lex [c] & LEX_IS_SYMBOL_COMPONENT)
  46. #define IS_WHITESPACE(c)        (lex [c] & LEX_IS_WHITESPACE)
  47. #define IS_LINE_SEPERATOR(c)        (lex [c] & LEX_IS_LINE_SEPERATOR)
  48. #define IS_COMMENT(c)            (lex [c] & LEX_IS_COMMENT_START)
  49. #define IS_LINE_COMMENT(c)        (lex [c] & LEX_IS_LINE_COMMENT_START)
  50.  
  51. void
  52. do_scrub_begin()
  53. {
  54.     const char *p;
  55.  
  56.     bzero (lex, sizeof(lex));        /* Trust NOBODY! */
  57.     lex [' ']        |= LEX_IS_WHITESPACE;
  58.     lex ['\t']        |= LEX_IS_WHITESPACE;
  59.     for (p =symbol_chars;*p;++p)
  60.         lex [*p] |= LEX_IS_SYMBOL_COMPONENT;
  61.     lex ['\n']        |= LEX_IS_LINE_SEPERATOR;
  62. #ifdef DONTDEF
  63.     lex [':']        |= LEX_IS_LINE_SEPERATOR;
  64. #endif
  65.     lex [';']        |= LEX_IS_LINE_SEPERATOR;
  66.     for (p=comment_chars;*p;p++)
  67.         lex[*p] |= LEX_IS_COMMENT_START;
  68.     for (p=line_comment_chars;*p;p++)
  69.         lex[*p] |= LEX_IS_LINE_COMMENT_START;
  70. }
  71.  
  72. FILE *scrub_file;
  73.  
  74. int
  75. scrub_from_file()
  76. {
  77.     return getc(scrub_file);
  78. }
  79.  
  80. void
  81. scrub_to_file(ch)
  82. int ch;
  83. {
  84.     ungetc(ch,scrub_file);
  85. }
  86.  
  87. char *scrub_string;
  88. char *scrub_last_string;
  89.  
  90. int
  91. scrub_from_string()
  92. {
  93.     return scrub_string == scrub_last_string ? EOF : *scrub_string++;
  94. }
  95.  
  96. void
  97. scrub_to_string(ch)
  98. int ch;
  99. {
  100.     *--scrub_string=ch;
  101. }
  102.  
  103. int
  104. do_scrub_next_char(get,unget)
  105. int (*get)();
  106. void (*unget)();
  107. /* FILE *fp; */
  108. {
  109.     /* State 0: beginning of normal line
  110.         1: After first whitespace on normal line (flush more white)
  111.         2: After first non-white on normal line (keep 1white)
  112.         3: after second white on normal line (flush white)
  113.         4: after putting out a .line, put out digits
  114.         5: parsing a string, then go to old-state
  115.         6: putting out \ escape in a "d string.
  116.         7: After putting out a .file, put out string.
  117.         8: After putting out a .file string, flush until newline.
  118.         -1: output string in out_string and go to the state in old_state
  119.         -2: flush text until a '*' '/' is seen, then go to state old_state
  120.     */
  121.  
  122.     static state;
  123.     static old_state;
  124.     static char *out_string;
  125.     static char out_buf[20];
  126.     static add_newlines;
  127.     int ch;
  128.  
  129.     if(state==-1) {
  130.         ch= *out_string++;
  131.         if(*out_string==0) {
  132.             state=old_state;
  133.             old_state=3;
  134.         }
  135.         return ch;
  136.     }
  137.     if(state==-2) {
  138.         for(;;) {
  139.             do ch=(*get)();
  140.             while(ch!=EOF && ch!='\n' && ch!='*');
  141.             if(ch=='\n' || ch==EOF)
  142.                 return ch;
  143.              ch=(*get)();
  144.              if(ch==EOF || ch=='/')
  145.                  break;
  146.             (*unget)(ch);
  147.         }
  148.         state=old_state;
  149.         return ' ';
  150.     }
  151.     if(state==4) {
  152.         ch=(*get)();
  153.         if(ch==EOF || (ch>='0' && ch<='9'))
  154.             return ch;
  155.         else {
  156.             while(ch!=EOF && IS_WHITESPACE(ch))
  157.                 ch=(*get)();
  158.             if(ch=='"') {
  159.                 (*unget)(ch);
  160.                 out_string="; .file ";
  161.                 old_state=7;
  162.                 state= -1;
  163.                 return *out_string++;
  164.             } else {
  165.                 while(ch!=EOF && ch!='\n')
  166.                     ch=(*get)();
  167.                 return ch;
  168.             }
  169.         }
  170.     }
  171.     if(state==5) {
  172.         ch=(*get)();
  173.         if(ch=='"') {
  174.             state=old_state;
  175.             return '"';
  176.         } else if(ch=='\\') {
  177.             state=6;
  178.             return ch;
  179.         } else if(ch==EOF) {
  180.             as_warn("End of file in string: inserted '\"'");
  181.              state=old_state;
  182.             (*unget)('\n');
  183.             return '"';
  184.         } else {
  185.             return ch;
  186.         }
  187.     }
  188.     if(state==6) {
  189.         state=5;
  190.         ch=(*get)();
  191.         switch(ch) {
  192.             /* This is neet.  Turn "string
  193.                more string" into "string\n  more string"
  194.              */
  195.         case '\n':
  196.             (*unget)('n');
  197.             add_newlines++;
  198.             return '\\';
  199.  
  200.         case '"':
  201.         case '\\':
  202.         case 'b':
  203.         case 'f':
  204.         case 'n':
  205.         case 'r':
  206.         case 't':
  207.         case '0':
  208.         case '1':
  209.         case '2':
  210.         case '3':
  211.         case '4':
  212.         case '5':
  213.         case '6':
  214.         case '7':
  215.             break;
  216.         default:
  217.             as_warn("Unknown escape '\\%c' in string: Ignored",ch);
  218.             break;
  219.  
  220.         case EOF:
  221.             as_warn("End of file in string: '\"' inserted");
  222.             return '"';
  223.         }
  224.         return ch;
  225.     }
  226.  
  227.     if(state==7) {
  228.         ch=(*get)();
  229.         state=5;
  230.         old_state=8;
  231.         return ch;
  232.     }
  233.  
  234.     if(state==8) {
  235.         do ch= (*get)();
  236.         while(ch!='\n');
  237.         state=0;
  238.         return ch;
  239.     }
  240.  
  241.  flushchar:
  242.     ch=(*get)();
  243.     switch(ch) {
  244.     case ' ':
  245.     case '\t':
  246.         do ch=(*get)();
  247.         while(ch!=EOF && IS_WHITESPACE(ch));
  248.         if(ch==EOF)
  249.             return ch;
  250.         if(IS_COMMENT(ch) || (state==0 && IS_LINE_COMMENT(ch)) || ch=='/' || IS_LINE_SEPERATOR(ch)) {
  251.             (*unget)(ch);
  252.             goto flushchar;
  253.         }
  254.         (*unget)(ch);
  255.         if(state==0 || state==2) {
  256.             state++;
  257.             return ' ';
  258.         } else goto flushchar;
  259.  
  260.     case '/':
  261.         ch=(*get)();
  262.         if(ch=='*') {
  263.             for(;;) {
  264.                 do {
  265.                     ch=(*get)();
  266.                     if(ch=='\n')
  267.                         add_newlines++;
  268.                 } while(ch!=EOF && ch!='*');
  269.                 ch=(*get)();
  270.                 if(ch==EOF || ch=='/')
  271.                     break;
  272.                 (*unget)(ch);
  273.             }
  274.             if(ch==EOF)
  275.                 as_warn("End of file in '/' '*' string: */ inserted");
  276.  
  277.             (*unget)(' ');
  278.             goto flushchar;
  279.         } else {
  280.             if(IS_COMMENT('/') || (state==0 && IS_LINE_COMMENT('/'))) {
  281.                 (*unget)(ch);
  282.                 ch='/';
  283.                 goto deal_misc;
  284.             }
  285.             if(ch!=EOF)
  286.                 (*unget)(ch);
  287.             return '/';
  288.         }
  289.         break;
  290.  
  291.     case '"':
  292.         old_state=state;
  293.         state=5;
  294.         return '"';
  295.         break;
  296.  
  297.     case '\'':
  298.         ch=(*get)();
  299.         if(ch==EOF) {
  300.             as_warn("End-of-file after a ': \000 inserted");
  301.             ch=0;
  302.         }
  303.         sprintf(out_buf,"(%d)",ch&0xff);
  304.         old_state=state;
  305.         state= -1;
  306.         out_string=out_buf;
  307.         return *out_string++;
  308.  
  309.     case ':':
  310.         if(state!=3)
  311.             state=0;
  312.         return ch;
  313.  
  314.     case '\n':
  315.         if(add_newlines) {
  316.             --add_newlines;
  317.             (*unget)(ch);
  318.         }
  319.     case ';':
  320.         state=0;
  321.         return ch;
  322.  
  323.     default:
  324.     deal_misc:
  325.         if(state==0 && IS_LINE_COMMENT(ch)) {
  326.             do ch=(*get)();
  327.             while(ch!=EOF && IS_WHITESPACE(ch));
  328.             if(ch==EOF) {
  329.                 as_warn("EOF in comment:  Newline inserted");
  330.                 return '\n';
  331.             }
  332.             if(ch<'0' || ch>'9') {
  333.                 while(ch!=EOF && ch!='\n')
  334.                     ch=(*get)();
  335.                 if(ch==EOF)
  336.                     as_warn("EOF in Comment: Newline inserted");
  337.                 state=0;
  338.                 return '\n';
  339.             }
  340.             (*unget)(ch);
  341.             old_state=4;
  342.             state= -1;
  343.             out_string=".line ";
  344.             return *out_string++;
  345.  
  346.         } else if(IS_COMMENT(ch)) {
  347.             do ch=(*get)();
  348.             while(ch!=EOF && ch!='\n');
  349.             if(ch==EOF)
  350.                 as_warn("EOF in comment:  Newline inserted");
  351.             state=0;
  352.             return '\n';
  353.  
  354.         } else if(state==0) {
  355.             state=2;
  356.             return ch;
  357.         } else if(state==1) {
  358.             state=2;
  359.             return ch;
  360.         } else {
  361.             return ch;
  362.  
  363.         }
  364.     case EOF:
  365.         if(state==0)
  366.             return ch;
  367.         as_warn("End-of-File not at end of a line");
  368.     }
  369.     return -1;
  370. }
  371.  
  372. #ifdef TEST
  373.  
  374. char comment_chars[] = "|";
  375. char line_comment_chars[] = "#";
  376.  
  377. main()
  378. {
  379.     int    ch;
  380.  
  381.     app_begin();
  382.     while((ch=do_scrub_next_char(stdin))!=EOF)
  383.         putc(ch,stdout);
  384. }
  385.  
  386. as_warn(str)
  387. char *str;
  388. {
  389.     fputs(str,stderr);
  390.     putc('\n',stderr);
  391. }
  392. #endif
  393.